package jmine.tec.web.servlet.taglib;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Date;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

/**
 * Tag lib utilitaria que calcula delta entre comeco e fim e imprime javascript que mostra esse tempo na tela para o usuario, em segundos.
 * 
 * @author Marcio Ribeiro (mmr)
 * @created Mar 3, 2009
 */
public class ChronoTag extends TagSupport {

    private String idToUpdate;

    private String msg;

    private boolean parent;

    private Date startTime;

    private static final DecimalFormat FORMATTER = new DecimalFormat("0.000");

    private static final String TIME_PATTERN = "{time}";

    /**
     * Pega tempo inicial.
     * 
     * @throws JspException caso algo de inesperado ocorra.
     * @return EVAL_PAGE.
     */
    @Override
    public int doStartTag() throws JspException {
        this.startTime = new Date();
        return EVAL_PAGE;
    }

    /**
     * Pega tempo final, calcula delta e imprime javascript que atualiza o campo com o id html passado com o tempo.
     * 
     * @throws JspException caso algo de inesperado ocorra.
     * @return SKIP_BODY.
     */
    @Override
    public int doEndTag() throws JspException {
        long time = new Date().getTime() - this.startTime.getTime();
        StringBuilder findElement = new StringBuilder();
        if (this.parent) {
            findElement.append("parent.");
        }
        findElement.append("document.getElementById('").append(this.idToUpdate).append("')");

        StringBuilder sb = new StringBuilder();
        sb.append("<script type='text/javascript'>");
        sb.append("if(parent && parent.window && parent.window.$){");
        sb.append("var elem = parent.window.$('.").append(this.idToUpdate).append("');");
        sb.append("elem.html('<div style=\"display: none\">"); // como pode jogar "contra", por enquanto, não deve ser visível para o
                                                               // usuario.
        sb.append(this.msg.replace(TIME_PATTERN, this.formatTime(time)));
        sb.append("</div>');");
        sb.append("} else {");
        sb.append("if(").append(findElement).append(")");
        sb.append(findElement).append(".innerHTML = '<div style=\"display: none\">");
        sb.append(this.msg.replace(TIME_PATTERN, this.formatTime(time)));
        sb.append("</div>';");
        sb.append("}");
        sb.append("</script>");
        try {
            this.pageContext.getOut().write(sb.toString());
        } catch (IOException e) {
            throw new JspException(e);
        }
        return SKIP_BODY;
    }

    /**
     * Formata tempo.
     * 
     * @param time tempo em milisegundos.
     * @return string com tempo formatado em segundos.
     */
    private String formatTime(long time) {
        final double mili = 1000d;
        return FORMATTER.format(time / mili);
    }

    /**
     * @return valor do campo idToUpdate.
     */
    public String getIdToUpdate() {
        return this.idToUpdate;
    }

    /**
     * Define valor para campo idToUpdate.
     * 
     * @param idToUpdate valor para campo idToUpdate.
     */
    public void setIdToUpdate(String idToUpdate) {
        this.idToUpdate = idToUpdate;
    }

    /**
     * @return valor do campo msg.
     */
    public String getMsg() {
        return this.msg;
    }

    /**
     * Define valor para campo msg.
     * 
     * @param msg valor para campo msg.
     */
    public void setMsg(String msg) {
        this.msg = msg;
    }

    /**
     * @return valor do campo parent.
     */
    public boolean isParent() {
        return this.parent;
    }

    /**
     * Define valor para campo parent.
     * 
     * @param parent valor para campo parent.
     */
    public void setParent(boolean parent) {
        this.parent = parent;
    }

}
